﻿using System;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using FutureTech.ComponentModel;

namespace FutureTech.Network
{
        /// <summary>
        /// 帧
        /// </summary>
        public abstract class Frame : NotifyPropertyChangedObject
        {
                #region 构造函数

                /// <summary>
                /// Initializes a new instance of the <see cref="Frame"/> class.
                /// </summary>
                /// <param name="buffer">The buffer.</param>
                protected Frame(Byte[] buffer)
                {
                        Contract.Requires(buffer != null);
                        Contract.Requires(buffer.Length > 3);

                        Buffer = buffer;
                }

                #endregion

                #region 常量

                /// <summary>
                /// 帧起始字节
                /// </summary>
                public const Byte StartByte = 0XFF;

                #endregion

                #region 属性

                /// <summary>
                /// 起始码
                /// </summary>
                public Byte Start
                {
                        get
                        {
                                Contract.Requires(Buffer != null);

                                return Buffer[0];
                        }
                        protected set
                        {
                                Contract.Requires(Buffer != null);

                                Buffer[0] = value;
                        }


                }

                /// <summary>
                /// 功能码
                /// </summary>
                public Byte Flag
                {
                        get
                        {
                                Contract.Requires(Buffer != null);

                                return Buffer[1];
                        }
                        protected set
                        {
                                Contract.Requires(Buffer != null);

                                Buffer[1] = value;
                        }
                }

                /// <summary>
                /// 校验码
                /// </summary>
                public Byte Check
                {
                        get
                        {
                                Contract.Requires(Buffer != null);

                                return Buffer[Buffer.Length-1];
                        }
                        protected set
                        {
                                Contract.Requires(Buffer != null);

                                Buffer[Buffer.Length-1] = value;
                        }


                }

                private byte[] _buffer;

                /// <summary>
                /// 内容
                /// </summary>
                public Byte[] Buffer
                {
                        get
                        {
                                Contract.Ensures(Contract.Result<Byte[]>() != null);

                                return _buffer;
                        }
                        protected set
                        {
                                Contract.Requires(value != null);

                                _buffer = value;
                        }


                }

                #endregion


                #region 方法


                /// <summary>
                /// 校验缓存区头
                /// </summary>
                /// <param name="buffer">The buffer.</param>
                /// <returns></returns>
                public static bool HeaderCheck(byte[] buffer)
                {
                        if (buffer == null)
                        {
                                return false;
                        }

                        if (buffer.Length < 2)
                        {
                                return false;
                        }

                        if (buffer[0] != StartByte)
                        {
                                return false;
                        }

                        return true;
                }

                /// <summary>
                /// 计算和校验
                /// </summary>
                /// <returns></returns>
                public Byte ComputerCheck()
                {
                        Contract.Requires(Buffer != null);

                        int total = 0;
                        for (int i = 1; i < Buffer.Length - 1; i++)
                        {
                                total += Buffer[i];
                        }
                        return (Byte)(total % 256);
                }

                /// <summary>
                /// 计算和校验并更新缓冲区
                /// </summary>
                public void UpdateCheck()
                {
                        Contract.Requires(Buffer != null);

                        Check = ComputerCheck();
                }

                #endregion

        }
}
